#include <string.h>
#include <unistd.h>
#include <hwicodec_common.h>
#ifdef DMALLOC
#include <imp/dmalloc.h>
#endif
int deadzone[4] = {0x00000015, 0x0000000b, 0x00000015, 0x0000000b /*deadzone[4]*/};

int hwicodec_pf_h264e_init_bpool(hwicodec_t *h, hwicodec_soc_binfo_t *pbinfo)
{
	int rdnum = 0,rdsnum =0, encnum = 0, bsnum = 0, dmanum = 0, extnum = 0, ncunum = 0;
	int y_rdsize = 0, y_rdssize =0, y_encsize = 0, bssize = 0, dmasize = 0, y_extsize = 0, y_ncusize = 0;
	int width_cnt = 0;
	int height_cnt = 0;

	hwicodec_h264e_param_t *param = &h->param.param.h264e_param;
	hwicodec_soc_bpool_t *bpool = &h->soc.bpool;
	int width = param->i_mb_width * 16;
	int height = param->i_mb_height * 16;
	hwicodec_mmcut_t mmcut[C_CHN_NUM_MAX * C_VB_NUM_MAX];
	int mcidx = 0, i = 0;

	bpool->vb_num = C_SOC_VB_MAX;
	bpool->vbinfo[C_SOC_VB_RD].type = C_SOC_VB_RD;
	rdnum = bpool->vbinfo[C_SOC_VB_RD].num = h->param.param.h264e_param.i_req_rdnum;
	bpool->vbinfo[C_SOC_VB_RDS].type = C_SOC_VB_RDS;
	rdsnum = bpool->vbinfo[C_SOC_VB_RDS].num = h->param.param.h264e_param.i_req_rdsnum;

	bpool->vbinfo[C_SOC_VB_ENC].type = C_SOC_VB_ENC;
	encnum = bpool->vbinfo[C_SOC_VB_ENC].num = param->b_user_fenc ? 0 : param->i_threads;
	bpool->vbinfo[C_SOC_VB_BS].type = C_SOC_VB_BS;
	bsnum = bpool->vbinfo[C_SOC_VB_BS].num = param->i_threads;
	bpool->vbinfo[C_SOC_VB_DMA].type = C_SOC_VB_DMA;
	dmanum = bpool->vbinfo[C_SOC_VB_DMA].num = param->i_threads;
	bpool->vbinfo[C_SOC_VB_EXT].type = C_SOC_VB_EXT;
	if (param->b_use_dn != 0) {
		extnum = bpool->vbinfo[C_SOC_VB_EXT].num = param->i_threads;
	}

	bpool->vbinfo[C_SOC_VB_NCU].type = C_SOC_VB_NCU;
	if (param->b_use_ncu != 0)
		ncunum = bpool->vbinfo[C_SOC_VB_NCU].num = param->i_threads;

	bpool->buf_num = rdnum + encnum + bsnum + dmanum + extnum + ncunum + rdsnum;

	y_rdsize = hwicodec_cal_bufsize(h, &pbinfo[C_SOC_VB_RD], width, height);
	y_rdssize = hwicodec_cal_bufsize(h,&pbinfo[C_SOC_VB_RDS],width,height);
	if (!param->b_user_fenc) {
		y_encsize = hwicodec_cal_bufsize(h, &pbinfo[C_SOC_VB_ENC], width, height);
	}
#ifndef CONFIG_SINGLE_BS
	bssize = hwicodec_cal_bufsize(h, &pbinfo[C_SOC_VB_BS], width, height);
#endif
	width_cnt = (width+15)/16;
	height_cnt = (height+15)/16;
	dmasize = 16*1024 + ((width_cnt*height_cnt)+1024)*2;
	pbinfo[C_SOC_VB_DMA].bufsize = dmasize;
	dmasize = hwicodec_cal_bufsize(h, &pbinfo[C_SOC_VB_DMA], width, height);

	if (param->b_use_dn != 0) {
		y_extsize = hwicodec_cal_bufsize(h, &pbinfo[C_SOC_VB_EXT], width, height);
	}
#if 0
	if (param->b_use_ncu != 0) {
		y_ncusize = hwicodec_cal_bufsize(h, &pbinfo[C_SOC_VB_NCU], width, height);
	}
#endif

	/*IC_VPU内存计算公式：buffsharesize+DMAsize(128字节对齐)*/
	/*bpool->buf_size = ((width_cnt*16)*(height_cnt*24 + 256*1.5)) + ((16*1024 + (width_cnt*(height_cnt*16)+1024)*2)+127)/128*128;*/

	/*因为buffsharesize新旧公式基本一致，所以只修改了DMAsize公式:搜索dmasize，计算可以节省1M左右*/
	bpool->buf_size = (y_rdsize*3/2+C_VB_ALIGN)*rdnum+(y_rdssize*3/2+C_VB_ALIGN)*rdsnum+(y_encsize*3/2+C_VB_ALIGN)*encnum+bssize*bsnum+dmasize*dmanum+(y_extsize*3/2+C_VB_ALIGN)*extnum + ncunum * y_ncusize;

	if ((bpool->buf_base_v = (intptr_t)h->param.ckmalloc(h->param.index, bpool->buf_size, C_VB_ALIGN)) == 0) {
		hwicodec_log(h, C_LOG_ERROR, "malloc buf_base size:%d failed\n", bpool->buf_size);
		goto err_malloc_buf_base;
	}

	memset(mmcut, 0, sizeof(hwicodec_mmcut_t));
	for (i = 0; i < rdnum; i++, mcidx++) {
		mmcut[mcidx].type = C_SOC_VB_RD;
		mmcut[mcidx].size = c_align(y_rdsize * 3 / 2, pbinfo[C_SOC_VB_RD].align, pbinfo[C_SOC_VB_RD].disalign);
		mmcut[mcidx].ysize = y_rdsize;
	}

	for (i = 0; i < encnum; i++, mcidx++) {
		mmcut[mcidx].type = C_SOC_VB_ENC;
		mmcut[mcidx].size = c_align(y_encsize * 3 / 2, pbinfo[C_SOC_VB_ENC].align, pbinfo[C_SOC_VB_ENC].disalign);
		mmcut[mcidx].ysize = y_encsize;
	}

	for (i = 0; i < bsnum; i++, mcidx++) {
		mmcut[mcidx].type = C_SOC_VB_BS;
		mmcut[mcidx].size = bssize;
		mmcut[mcidx].ysize = 0;
	}

	for (i = 0; i < dmanum; i++, mcidx++) {
		mmcut[mcidx].type = C_SOC_VB_DMA;
		mmcut[mcidx].size = dmasize;
		mmcut[mcidx].ysize = 0;
	}

	for (i = 0; i < extnum; i++, mcidx++) {
		mmcut[mcidx].type = C_SOC_VB_EXT;
		mmcut[mcidx].size = c_align(y_extsize * 3 / 2, pbinfo[C_SOC_VB_EXT].align, pbinfo[C_SOC_VB_EXT].disalign);
		mmcut[mcidx].ysize = y_extsize;
	}

	for (i = 0; i < ncunum; i++, mcidx++) {
		mmcut[mcidx].type = C_SOC_VB_NCU;
		mmcut[mcidx].size = y_ncusize;
		mmcut[mcidx].ysize = 0;
	}

	for (i = 0; i < rdsnum; i++, mcidx++) {
		mmcut[mcidx].type = C_SOC_VB_RDS;
		mmcut[mcidx].size = c_align(y_rdssize * 3 / 2, pbinfo[C_SOC_VB_RD].align, pbinfo[C_SOC_VB_RD].disalign);
		mmcut[mcidx].ysize = y_rdssize;
	}

	if (mcidx != bpool->buf_num) {
		hwicodec_log(h, C_LOG_ERROR, "mcidx err\n");
		goto err_mcidx;
	}

	if(hwicodec_init_soc_bpool(h, pbinfo, mmcut, width, height, param->b_tlb) < 0) {
		hwicodec_log(h, C_LOG_ERROR, "init_soc_bpool\n");
		goto err_init_soc_bpool;
	}

	return 0;

err_init_soc_bpool:
err_mcidx:
	h->param.ckfree(h->param.index, (void *)bpool->buf_base_v);
err_malloc_buf_base:
	return -1;
}
